/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package src;

import java.io.IOException;
import org.apache.pdfbox.*;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.exceptions.COSVisitorException;

/**
 * JpdfSetField permite tomar un formulario pdf, modificar sus campos (cargar
 * valores en los mismos) y grabar un nuevo pdf con los valores modificados
 * Se puede utilizar esta clase para setear los distintos campos del formulario
 * y luego visualizarlo y/o mandarlo a imprimir
 * Version modificada basada en clase SetField de los ejemplos publicados por
 * Apache Org
 * Requiere Apache Org PDFBOX framework http://pdfbox.apache.org
 *
 * @author Apache Org, G. Cherencio
 * @version 1.0
 */
public final class JpdfSetField {

    String pdfName = null;
    String pdfSaveAs = null;
    PDDocument pdf = null;
    PDDocumentCatalog docCatalog = null;
    PDAcroForm acroForm = null;

    public JpdfSetField() {
    }

    public JpdfSetField(final String pdfName) {
        this(pdfName, "new_" + pdfName);
    }

    public JpdfSetField(final String pdfName, final String newPdfName) {
        setPdfName(pdfName);
        setNewPdfName(newPdfName);
    }
// SETTERS

    public void setPdfName(final String pdfstr) {
        pdfName = pdfstr;
        try {
            pdf = PDDocument.load(pdfName);
            docCatalog = pdf.getDocumentCatalog();
            acroForm = docCatalog.getAcroForm();
        } catch (IOException ioe) {
            blank();
        }
    }

    public void setNewPdfName(final String pdf) {
        pdfSaveAs = pdf;
    }

    public void setPdf(PDDocument p) {
        pdf = p;
    }

    /**
     * Carga el valor de un campo del formulario
     *
     * @param fieldName nombre del campo
     * @param fieldValue valor del campo
     */
    public void setValue(final String fieldName, final String fieldValue) {
        if (acroForm != null) {
            try {
                PDField field = acroForm.getField(fieldName);
                if (field != null) {
                    field.setValue(fieldValue);
                } else {
                    System.err.println("PdfSetField.setValue(): [" + fieldName + "] no existe en documento!");
                }
            } catch (IOException ioe) {
            }
        }
    }
// GETTERS

    public PDDocument getPdf() {
        return pdf;
    }

    public String getPdfName() {
        return pdfName;
    }

    public String getNewPdfName() {
        return pdfSaveAs;
    }

    public PDField getField(final String name) {
        if (acroForm != null) {
            try {
                return acroForm.getField(name);
            } catch (IOException ioe) {
            }
        }
        return null;
    }
// CUSTOM

    public boolean saveAs(final String saveAs) {
        pdfSaveAs = saveAs;
        return save();
    }

    public boolean save() {
        if (pdf != null) {
            try {
                if (pdfSaveAs == null) {
                    pdfSaveAs = "new_" + pdfName;
                }
                pdf.save(pdfSaveAs);
            } catch (COSVisitorException cve) {
                return false;
            } catch (IOException ioe) {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }

    public boolean close() {
        if (pdf != null) {
            try {
                pdf.close();
                blank();
            } catch (IOException ioe) {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }
// limpia las referencias a objetos que ya no se requieren

    private void blank() {
        pdf = null;
        pdfName = null;
        docCatalog = null;
        acroForm = null;
    }

    /**
     * Ejemplo de uso de objeto JpdfSetField
     * Ejecuta PDFDebugger para ver metadata de A4b.pdf
     * Setea campos del formulario A4b.pdf utilizando objeto JpdfSetField
     * graba nuevo pdf new_A4b.pdf
     * Ejecuta PDFReader para visualizar new_A4b.pdf
     */
    public static void main(String[] args) {
        //java -jar pdfbox-app-x.y.z.jar PDFDebugger [PDF file]
        String arg[] = new String[]{"PDFDebugger", "A4b.pdf"};
        PDFBox.main(arg);

        JpdfSetField p = new JpdfSetField("A4b.pdf");
        // seteo los campos de la primer fila
        p.setValue("orden1", "1");
        p.setValue("dni1", "22111333");
        p.setValue("lf1", "L");
        p.setValue("nombre", "cherencio, guillermo");
        p.setValue("apto1", "si");
        p.setValue("obser1", "observaciones1");

        // seteo los campos de la segunda fila
        p.setValue("n3", "2");
        p.setValue("dni2", "33444555");
        p.setValue("lf2", "F");
        p.setValue("nom2", "romero, juan");
        p.setValue("apto2", "si");
        p.setValue("obs2", "observaciones2");

        p.save();
        p.close();

        // muestro nuevo pdf creado
        //java -jar pdfbox-app-x.y.z.jar PDFReader [PDF file]
        arg[0] = "PDFReader";
        arg[1] = p.getNewPdfName();
        PDFBox.main(arg);

    }
}